home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Utilities / Type1Manager / src / token.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-12  |  26.5 KB  |  1,273 lines

  1. /* $XConsortium: token.c,v 1.3 94/02/04 17:07:17 gildea Exp $ */
  2. /* Copyright International Business Machines,Corp. 1991
  3.  * All Rights Reserved
  4.  *
  5.  * License to use, copy, modify, and distribute this software
  6.  * and its documentation for any purpose and without fee is
  7.  * hereby granted, provided that the above copyright notice
  8.  * appear in all copies and that both that copyright notice and
  9.  * this permission notice appear in supporting documentation,
  10.  * and that the name of IBM not be used in advertising or
  11.  * publicity pertaining to distribution of the software without
  12.  * specific, written prior permission.
  13.  *
  14.  * IBM PROVIDES THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES
  15.  * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
  16.  * LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
  18.  * THIRD PARTY RIGHTS.  THE ENTIRE RISK AS TO THE QUALITY AND
  19.  * PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
  20.  * OR MAINTAIN, BELONGS TO THE LICENSEE.  SHOULD ANY PORTION OF
  21.  * THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM) ASSUMES
  22.  * THE ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION.  IN
  23.  * NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  25.  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  26.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  27.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  28.  * SOFTWARE.
  29.  */
  30. /* Authors: Sig Nin & Carol Thompson IBM Almaden Research Laboratory */
  31.  
  32. #ifndef T1GST
  33. #include "global.h"
  34. #endif
  35.  
  36. #include "digit.h"
  37. #include "tokst.h"
  38. #include "hdigit.h"
  39.  
  40.  
  41. static double P10(long exponent);
  42. static void save_digraph(int ch);
  43.  
  44.  
  45. /*
  46.  * -------------------------------------------------------------------
  47.  * Globals
  48.  * -------------------------------------------------------------------
  49.  */
  50. /* These variables are set by the caller */
  51. char *tokenStartP;        /* Pointer to token buffer in VM */
  52. char *tokenMaxP;        /* Pointer to last byte in buffer + 1 */
  53.  
  54. /* These variables are set by TOKEN */
  55. int tokenLength;        /* Characters in token */
  56. boolean tokenTooLong;        /* Token too long for buffer */
  57. int tokenType;            /* Type of token identified */
  58. psvalue tokenValue;        /* Token value */
  59.  
  60.  
  61. /*
  62.  * -------------------------------------------------------------------
  63.  * Private variables
  64.  * -------------------------------------------------------------------
  65.  */
  66. static F_FILE *inputFileP;    /* Current input file */
  67.  
  68. /* Token */
  69. static char *tokenCharP;    /* Pointer to next character in token */
  70.  
  71.  
  72. /*
  73.  * -------------------------------------------------------------------
  74.  * Private routines for manipulating numbers
  75.  * -------------------------------------------------------------------
  76.  */
  77.  
  78. #define Exp10(e) \
  79. ((e) == 0\
  80.  ? (double)(1.0)\
  81.  : (-64 <= (e) && (e) <= 63\
  82.     ? Exp10T[(e)+64]\
  83.     : P10(e)\
  84.    )\
  85. )
  86.  
  87. const static double Exp10T[128] =
  88. {
  89.     1e-64, 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57,
  90.     1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49,
  91.     1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41,
  92.     1e-40, 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33,
  93.     1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25,
  94.     1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, 1e-18, 1e-17,
  95.     1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9,
  96.     1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
  97.     1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
  98.     1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
  99.     1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23,
  100.     1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31,
  101.     1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
  102.     1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47,
  103.     1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54, 1e55,
  104.     1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63
  105. };
  106.  
  107. static double P10(long exponent)
  108. {
  109.     double value, power;
  110.  
  111.     if (exponent < 0)
  112.     {
  113.         power = 0.1;
  114.         value = (exponent & 1 ? power : 1.0);
  115.         exponent = -(++exponent >> 1);    /* portable C for -(exponent/2) */
  116.     }
  117.     else
  118.     {
  119.         power = 10.0;
  120.         value = (exponent & 1 ? power : 1.0);
  121.         exponent = exponent >> 1;
  122.     }
  123.  
  124.     while (exponent > 0)
  125.     {
  126.         power *= power;
  127.         if (exponent & 1)
  128.             value *= power;
  129.         exponent >>= 1;
  130.     }
  131.  
  132.     return (value);
  133. }
  134.  
  135.  
  136. /*
  137.  * -------------------------------------------------------------------
  138.  * Private routines and macros for manipulating the input
  139.  * -------------------------------------------------------------------
  140.  */
  141.  
  142. /* Get next character from the input --
  143.  *
  144.  */
  145. #define next_ch()    (T1getc(inputFileP))
  146.  
  147. /* Push a character back into the input --
  148.  *
  149.  * Ungetc of EOF will fail, but that's ok: the next getc will
  150.  * return EOF.
  151.  *
  152.  * NOTE:  These macros are presently written to return the character
  153.  * pushed, or EOF if none was pushed.  However, they are not
  154.  * required to return anything in particular, and callers should
  155.  * not rely on the returned value.
  156.  */
  157. #define back_ch(ch)   (T1ungetc(ch, inputFileP))
  158.  
  159. /* Push a character back into the input if it was not white space.
  160.  * If it is a carriage return (\r) then check next char for
  161.  * linefeed and consume them both, otherwise put next char back.
  162.  *
  163.  */
  164. #define back_ch_not_white(ch) \
  165. (\
  166. isWHITE_SPACE(ch)\
  167.  ? ((ch == '\r')\
  168.    ? (((ch = next_ch()) == '\n')\
  169.      ? EOF\
  170.      : back_ch(ch)\
  171.      )\
  172.    : EOF\
  173.    )\
  174.  : back_ch(ch)\
  175. )
  176.  
  177.  
  178. /*
  179.  * -------------------------------------------------------------------
  180.  * Private routines and macros for manipulating the token buffer
  181.  * -------------------------------------------------------------------
  182.  */
  183.  
  184. /* Add a character to the token
  185.  * ---- use ONLY when you KNOW that this character will
  186.  *      be stored within the token buffer.
  187.  */
  188. #define save_unsafe_ch(ch) (*tokenCharP++ = ch)
  189.  
  190. /* Add a character to the token, if not too long to fit */
  191. #define save_ch(ch) ((tokenCharP < tokenMaxP) ? save_unsafe_ch(ch) : (tokenTooLong = TRUE))
  192. #define save_ch_no_inc(ch) ((tokenCharP < tokenMaxP) && (*tokenCharP = ch))
  193.  
  194.  
  195. /*
  196.  * -------------------------------------------------------------------
  197.  * Action Routines
  198.  *
  199.  *  These routines all
  200.  *    -- take int ch as a parameter
  201.  *    -- return int ch if no token was recognized, DONE otherwise
  202.  *    -- leave the next character in the input, if returning DONE
  203.  * -------------------------------------------------------------------
  204.  */
  205. #define DONE  (256)
  206.  
  207. /* Get the next input character */
  208. static int __stdargs  next_char(int ch)
  209. {
  210.     return (next_ch());
  211. }
  212.  
  213. /* Add character to token */
  214. static int __stdargs  add_char(int ch)
  215. {
  216.     save_ch(ch);
  217.     return (next_ch());
  218. }
  219.  
  220.  
  221. /* -------------------------------------------------------------------
  222.  * Skip white space and comments
  223.  */
  224.  
  225. /* Skip white space */
  226. static int __stdargs  skip_space(int ch)
  227. {
  228.     do
  229.     {
  230.         ch = next_ch();
  231.     }
  232.     while (isWHITE_SPACE(ch));
  233.     return (ch);
  234. }
  235.  
  236. /* Skip comments */
  237. static int __stdargs  skip_comment(int ch)
  238. {
  239.     do
  240.     {
  241.         ch = next_ch();
  242.     }
  243.     while (isCOMMENT(ch));
  244.     return (ch);
  245. }
  246.  
  247. /* -------------------------------------------------------------------
  248.  * Collect value elements for a number
  249.  */
  250.  
  251. /* decimal integer or real number mantissa */
  252. static int m_sign;
  253. static long m_value;
  254. static long m_scale;
  255.  
  256. /* real number exponent */
  257. static int e_sign;
  258. static long e_value;
  259. static long e_scale;
  260.  
  261. /* radix number */
  262. static long r_base;
  263. static long r_value;
  264. static long r_scale;
  265.  
  266. static int __stdargs  add_sign(int ch)
  267. {
  268.     m_sign = ch;
  269.     save_unsafe_ch(ch);
  270.     return (next_ch());
  271. }
  272.  
  273. static int __stdargs  add_1st_digits(int ch)
  274. {
  275.     m_sign = '+';
  276.     return (add_digits(ch));
  277. }
  278.  
  279. static int __stdargs  add_digits(int ch)
  280. {
  281.     long value, p_value, scale;
  282.     int digit;
  283.  
  284.     /* On entry, expect m_sign to be set to '+' or '-';
  285.    *  ch is a decimal digit.
  286.    * Expect at most one character saved at this point,
  287.    *  a sign.  This routine will save up to 10 more
  288.    *  characters without checking the buffer boundary.
  289.    */
  290.  
  291.     value = ch - '0';
  292.     save_unsafe_ch(ch);
  293.     ch = next_ch();
  294.  
  295.     while (isDECIMAL_DIGIT(ch) && value < (MAX_INTEGER / 10))
  296.     {
  297.         value = (value << 3) + (value << 1) + (ch - '0');
  298.         save_unsafe_ch(ch);
  299.         ch = next_ch();
  300.     }
  301.  
  302.     /* Quick exit for small integers --
  303.    *    |x| <= 10*((MAX_INTEGER/10)-1)+9
  304.    *    |x| <= 2,147,483,639 for 32 bit integers
  305.    */
  306.     if (isNUMBER_ENDER(ch))
  307.     {
  308.         back_ch_not_white(ch);
  309.         tokenValue.integer = (m_sign == '-' ? -value : value);
  310.         tokenType = TOKEN_INTEGER;
  311.         return (DONE);
  312.     }
  313.  
  314.     /* Handle additional digits.  Beyond the boundary case,
  315.    *   10*(MAX_INTEGER/10) <= |number| <= MAX_INTEGER
  316.    * just count the digits: the number is too large to
  317.    * represent as an integer and will be returned as a real.
  318.    * The mantissa of a real holds fewer bits than an integer.
  319.    */
  320.     p_value = value;
  321.     value = (m_sign == '-' ? -value : value);
  322.     scale = 0;
  323.  
  324.     if (isDECIMAL_DIGIT(ch))
  325.     {
  326.  
  327.         /* Handle the boundary case */
  328.         if (p_value == (MAX_INTEGER / 10))
  329.         {
  330.             digit = ch - '0';
  331.  
  332.             /* Must handle positive and negative values separately  */
  333.             /* for 2's complement arithmetic */
  334.             if (value > 0)
  335.             {
  336.                 if (digit <= MAX_INTEGER % 10)
  337.                     value = (value << 3) + (value << 1) + digit;
  338.                 else
  339.                     ++scale;    /* Too big, just count it */
  340.             }
  341.             else
  342.             {
  343.                 /* Use positive % operands for portability */
  344.                 if (digit <= -(MIN_INTEGER + 10) % 10)
  345.                     value = (value << 3) + (value << 1) - digit;
  346.                 else
  347.                     ++scale;    /* Too big, just count it */
  348.             }
  349.         }
  350.         else
  351.             ++scale;/* Not boundary case, just count digit */
  352.  
  353.         save_unsafe_ch(ch);
  354.         ch = next_ch();
  355.  
  356.         /* Continue scanning digits, but can't store them */
  357.         while (isDECIMAL_DIGIT(ch))
  358.         {
  359.             ++scale;
  360.             save_ch(ch);
  361.             ch = next_ch();
  362.         }
  363.     }
  364.  
  365.     /* Continue from here scanning radix integer or real */
  366.     m_value = value;
  367.     m_scale = scale;
  368.  
  369.     /* Initialize for possible real */
  370.     e_sign = '+';
  371.     e_value = 0;
  372.     e_scale = 0;
  373.  
  374.     return (ch);
  375. }
  376.  
  377. static int __stdargs  add_1st_decpt(int ch)
  378. {
  379.     m_sign = '+';
  380.     return (add_decpt(ch));
  381. }
  382.  
  383. static int __stdargs  add_decpt(int ch)
  384. {
  385.     /* On entry, expect m_sign to be set to '+' or '-' */
  386.     m_value = 0;
  387.     m_scale = 0;
  388.     save_unsafe_ch(ch);
  389.     return (next_ch());
  390. }
  391.  
  392. static int __stdargs  add_fraction(int ch)
  393. {
  394.     long value, scale;
  395.     int digit;
  396.  
  397.     /* On entry, expect m_value and m_scale to be initialized,
  398.    * and m_sign to be set to '+' or '-'.  Expect m_value and m_sign
  399.    * to be consistent (this is not checked).
  400.    */
  401.     value = m_value;
  402.     scale = m_scale;
  403.  
  404.     /* Scan leading zeroes */
  405.     if (value == 0)
  406.     {
  407.         while (ch == '0')
  408.         {
  409.             --scale;
  410.             save_ch(ch);
  411.             ch = next_ch();
  412.         }
  413.  
  414.         /* Scan first significant digit */
  415.         if (isDECIMAL_DIGIT(ch))
  416.         {
  417.             --scale;
  418.             value = ch - '0';
  419.             value = (m_sign == '-' ? -value : value);
  420.             save_ch(ch);
  421.             ch = next_ch();
  422.         }
  423.         else
  424.             /* no significant digits -- number is zero */
  425.             scale = 0;
  426.     }
  427.     /* value != 0 || value == 0 && !isDECIMAL_DIGIT(ch) */
  428.  
  429.     /* Scan additional significant digits */
  430.     if (isDECIMAL_DIGIT(ch))
  431.     {
  432.         if (value > 0)
  433.         {
  434.             while (isDECIMAL_DIGIT(ch) && value < (MAX_INTEGER / 10))
  435.             {
  436.                 --scale;
  437.                 value = (value << 3) + (value << 1) + (ch - '0');
  438.                 save_ch(ch);
  439.                 ch = next_ch();
  440.             }
  441.             /* Check boundary case */
  442.             if (isDECIMAL_DIGIT(ch) && value == (MAX_INTEGER / 10))
  443.             {
  444.                 digit = ch - '0';
  445.                 if (digit <= MAX_INTEGER % 10)
  446.                 {
  447.                     --scale;
  448.                     value = (value << 3) + (value << 1) + digit;
  449.                     save_ch(ch);
  450.                     ch = next_ch();
  451.                 }
  452.             }
  453.         }
  454.         else
  455.         {
  456.             /* value < 0 */
  457.             while (isDECIMAL_DIGIT(ch) && value > -(-(MIN_INTEGER + 10) / 10 + 1))
  458.             {
  459.                 /* Use positive / operands for portability */
  460.                 --scale;
  461.                 value = (value << 3) + (value << 1) - (ch - '0');
  462.                 save_ch(ch);
  463.                 ch = next_ch();
  464.             }
  465.             /* Check boundary case */
  466.             if (isDECIMAL_DIGIT(ch)
  467.                 && value == -(-(MIN_INTEGER + 10) / 10 + 1))
  468.             {
  469.                 digit = ch - '0';
  470.                 if (digit <= -(MIN_INTEGER + 10) % 10)
  471.                 {
  472.                     /* Use positive % operands for portability */
  473.                     --scale;
  474.                     value = (value << 3) + (value << 1) - digit;
  475.                     save_ch(ch);
  476.                     ch = next_ch();
  477.                 }
  478.             }
  479.         }
  480.  
  481.         /* Additional digits can be discarded */
  482.         while (isDECIMAL_DIGIT(ch))
  483.         {
  484.             save_ch(ch);
  485.             ch = next_ch();
  486.         }
  487.     }
  488.  
  489.     /* Store results */
  490.     m_value = value;
  491.     m_scale = scale;
  492.  
  493.     /* Initialize for possible real */
  494.     e_sign = '+';
  495.     e_value = 0;
  496.     e_scale = 0;
  497.  
  498.     return (ch);
  499. }
  500.  
  501. static int __stdargs  add_e_sign(int ch)
  502. {
  503.     e_sign = ch;
  504.     save_ch(ch);
  505.     return (next_ch());
  506. }
  507.  
  508. static int __stdargs  add_exponent(int ch)
  509. {
  510.     long value, p_value;
  511.     long scale = 0;
  512.     int digit;
  513.  
  514.     /* On entry, expect e_sign to be set to '+' or '-' */
  515.  
  516.     value = ch - '0';
  517.     save_ch(ch);
  518.     ch = next_ch();
  519.  
  520.     while (isDECIMAL_DIGIT(ch) && value < (MAX_INTEGER / 10))
  521.     {
  522.         value = (value << 3) + (value << 1) + (ch - '0');
  523.         save_ch(ch);
  524.         ch = next_ch();
  525.     }
  526.  
  527.     p_value = value;
  528.     value = (e_sign == '-' ? -value : value);
  529.  
  530.     /* Handle additional digits.  Beyond the boundary case,
  531.    *   10*(MAX_INTEGER/10) <= |number| <= MAX_INTEGER
  532.    * just count the digits: the number is too large to
  533.    * represent as an integer.
  534.    */
  535.     if (isDECIMAL_DIGIT(ch))
  536.     {
  537.  
  538.         /* Examine boundary case */
  539.         if (p_value == (MAX_INTEGER / 10))
  540.         {
  541.             digit = ch - '0';
  542.  
  543.             /* Must handle positive and negative values separately */
  544.             /*  for 2's complement arithmetic */
  545.             if (value > 0)
  546.             {
  547.                 if (digit <= MAX_INTEGER % 10)
  548.                     value = (value << 3) + (value << 1) + digit;
  549.                 else
  550.                     ++scale;    /* Too big, just count it */
  551.             }
  552.             else
  553.             {
  554.                 /* Use positive % operands for portability */
  555.                 if (digit <= -(MIN_INTEGER + 10) % 10)
  556.                     value = (value << 3) + (value << 1) - digit;
  557.                 else
  558.                     ++scale;    /* Too big, just count it */
  559.             }
  560.         }
  561.         else
  562.             ++scale;/* Not boundary case, just count digit */
  563.  
  564.         save_ch(ch);
  565.         ch = next_ch();
  566.  
  567.         /* Continue scanning digits, but can't store any more */
  568.         while (isDECIMAL_DIGIT(ch))
  569.         {
  570.             ++scale;
  571.             save_ch(ch);
  572.             ch = next_ch();
  573.         }
  574.     }
  575.  
  576.     /* Store results */
  577.     e_value = value;
  578.     e_scale = scale;
  579.  
  580.     return (ch);
  581. }
  582.  
  583. static int __stdargs  add_radix(int ch)
  584. {
  585.     if (2 <= m_value && m_value <= 36 && m_scale == 0)
  586.     {
  587.         r_base = m_value;
  588.         save_ch(ch);
  589.         return (next_ch());
  590.     }
  591.     else
  592.     {
  593.         /* Radix invalid, complete a name token */
  594.         return (AAH_NAME(ch));
  595.     }
  596. }
  597.  
  598. static int __stdargs  add_r_digits(int ch)
  599. {
  600.     unsigned long value;
  601.     long radix, scale;
  602.     int digit;
  603.  
  604.     /* NOTE:  The syntax of a radix number allows only for
  605.    * values of zero or more.  The value will be stored as
  606.    * a 32 bit integer, which PostScript then interprets
  607.    * as signed.  This means, for example, that the numbers:
  608.    *
  609.    *     8#37777777777
  610.    *    10#4294967295
  611.    *    16#FFFFFFFF
  612.    *    36#1Z141Z3
  613.    *
  614.    * are all interpreted as -1.  This routine implements this
  615.    * idea explicitly:  it accumulates the number's value
  616.    * as unsigned, then casts it to signed when done.
  617.    */
  618.  
  619.     /* Expect r_base to be initialized */
  620.     radix = r_base;
  621.     value = 0;
  622.     scale = 0;
  623.  
  624.     /* Scan leading zeroes */
  625.     while (ch == '0')
  626.     {
  627.         save_ch(ch);
  628.         ch = next_ch();
  629.     }
  630.  
  631.     /* Handle first non-zero digit */
  632.     if ((digit = digit_value[ch]) < radix)
  633.     {
  634.         value = digit;
  635.         save_ch(ch);
  636.         ch = next_ch();
  637.  
  638.         /* Add digits until boundary case reached */
  639.         while ((digit = digit_value[ch]) < radix
  640.                && value < (MAX_ULONG / radix))
  641.         {
  642.             value = value * radix + digit;
  643.             save_ch(ch);
  644.             ch = next_ch();
  645.         };
  646.  
  647.         /* Scan remaining digits */
  648.         if ((digit = digit_value[ch]) < radix)
  649.         {
  650.  
  651.             /* Examine boundary case ---
  652.        *   radix*(MAX_ULONG/radix) <= number <= MAX_ULONG
  653.        */
  654.             if (value == (MAX_ULONG / radix) && digit <= MAX_ULONG % radix)
  655.                 value = value * radix + digit;
  656.             else
  657.                 ++scale;
  658.  
  659.             /* Continue scanning digits, but can't store them */
  660.             save_ch(ch);
  661.             ch = next_ch();
  662.             while (digit_value[ch] < radix)
  663.             {
  664.                 ++scale;
  665.                 save_ch(ch);
  666.                 ch = next_ch();
  667.             }
  668.         }
  669.     }
  670.  
  671.     /* Store result */
  672.     r_value = (long)value;    /* result is signed */
  673.     r_scale = scale;
  674.  
  675.     return (ch);
  676. }
  677.  
  678. /* -------------------------------------------------------------------
  679.  * Complete a number; set token type and done flag.
  680.  * Put current input character back, if it is not white space.
  681.  */
  682.  
  683. /* Done: Radix Number */
  684. static int __stdargs  RADIX_NUMBER(int ch)
  685. {
  686.     back_ch_not_white(ch);
  687.     if (r_scale == 0)
  688.     {
  689.         tokenValue.integer = r_value;
  690.         tokenType = TOKEN_INTEGER;
  691.     }
  692.     else
  693.     {
  694.         tokenType = TOKEN_NAME;
  695.     }
  696.     return (DONE);
  697. }
  698.  
  699. /* Done: Integer */
  700. static int __stdargs  INTEGER(int ch)
  701. {
  702.     back_ch_not_white(ch);
  703.     if (m_scale == 0)
  704.     {
  705.         tokenValue.integer = m_value;
  706.         tokenType = TOKEN_INTEGER;
  707.     }
  708.     else
  709.     {
  710.         tokenValue.real = (double)(m_value) * Exp10(m_scale);
  711.         tokenType = TOKEN_REAL;
  712.     }
  713.     return (DONE);
  714. }
  715.  
  716. /* Done: Real */
  717. static int __stdargs  REAL(int ch)
  718. {
  719.     double temp;
  720.  
  721.     back_ch_not_white(ch);
  722.  
  723.     /* NOTE: ignore e_scale, since e_value alone will cause
  724.    *   exponent overflow if e_scale > 0.
  725.    */
  726.  
  727.     /* HAZARD: exponent overflow of intermediate result
  728.    * (e.g., in 370 floating point); this should not be a problem
  729.    * with IEEE floating point.  Reduce exponent overflow hazard by
  730.    * combining m_scale and e_value first, if they have different signs,
  731.    * or multiplying m_value and one of the other factors, if both
  732.    * m_scale and e_value are negative.
  733.    */
  734.     if ((m_scale >= 0 && e_value <= 0)
  735.         || (m_scale <= 0 && e_value >= 0))
  736.     {
  737.         tokenValue.real = (double)(m_value) * Exp10(m_scale + e_value);
  738.     }
  739.     else
  740.     {
  741.         temp = (double)(m_value) * Exp10(m_scale);
  742.         tokenValue.real = temp * Exp10(e_value);
  743.     }
  744.  
  745.     tokenType = TOKEN_REAL;
  746.     return (DONE);
  747. }
  748.  
  749.  
  750. /* -------------------------------------------------------------------
  751.  * Assemble a hex string; set token type and done flag.
  752.  */
  753.  
  754. /* Done: Hex String */
  755. static int __stdargs  HEX_STRING(int ch)
  756. {
  757.     int value;
  758.  
  759.     while (TRUE)
  760.     {
  761.  
  762.         /* Process odd digit */
  763.         ch = next_ch();
  764.         if (!isHEX_DIGIT(ch))
  765.         {
  766.  
  767.             /* Skip white space */
  768.             while (isWHITE_SPACE(ch))
  769.                 ch = next_ch();
  770.  
  771.             /* Check for terminator */
  772.             if (!isHEX_DIGIT(ch))
  773.             {
  774.                 break;
  775.             }
  776.         }
  777.         value = digit_value[ch] << 4;
  778.  
  779.         /* Process even digit */
  780.         ch = next_ch();
  781.         if (!isHEX_DIGIT(ch))
  782.         {
  783.  
  784.             /* Skip white space */
  785.             while (isWHITE_SPACE(ch))
  786.                 ch = next_ch();
  787.  
  788.             /* Check for terminator */
  789.             if (!isHEX_DIGIT(ch))
  790.             {
  791.                 save_ch(value);
  792.                 break;
  793.             }
  794.         }
  795.         save_ch(value + digit_value[ch]);
  796.     }
  797.  
  798.     /* Classify result, based on why loop ended */
  799.     if (ch == '>')
  800.         tokenType = TOKEN_HEX_STRING;
  801.     else
  802.     {
  803.         /* save the invalid character for error reporting */
  804.         save_ch(ch);
  805.         tokenType = TOKEN_INVALID;
  806.     }
  807.  
  808.     return (DONE);
  809. }
  810.  
  811. /* -------------------------------------------------------------------
  812.  * Assemble a string; set token type and done flag
  813.  */
  814.  
  815. /* Save a backslash-coded character in a string --
  816.  *
  817.  *   Store the proper character for special cases
  818.  *   "\b", "\f", "\n", "\r", and "\t".
  819.  *
  820.  *   Decode and store octal-coded character, up to
  821.  *   three octal digits, "\o", "\oo", and "\ooo".
  822.  *
  823.  *   The sequence "\<newline>" is a line continuation,
  824.  *   so consume both without storing anything.
  825.  *
  826.  *   The sequence "\<EOF>" is an error; exit without
  827.  *   storing anything and let the caller handle it.
  828.  *
  829.  *   For other characters, including the sequences
  830.  *   "\\", "\(", and "\)", simply store the second
  831.  *   character.
  832.  */
  833. static void save_digraph(int ch)
  834. {
  835.     int value;
  836.  
  837.     switch (ch)
  838.     {
  839.  
  840.     case 'b':        /* backspace */
  841.         ch = '\b';
  842.         break;
  843.  
  844.     case 'f':        /* formfeed */
  845.         ch = '\f';
  846.         break;
  847.  
  848.     case 'n':        /* newline */
  849.         ch = '\n';
  850.         break;
  851.  
  852.     case 'r':        /* carriage return */
  853.         ch = '\r';
  854.         break;
  855.  
  856.     case 't':        /* horizontal tab */
  857.         ch = '\t';
  858.         break;
  859.  
  860.     case '\n':        /* line continuation -- consume it */
  861.         return;
  862.  
  863.     case '\r':        /* carriage return   -- consume it */
  864.         ch = next_ch();    /* look at next character, is it \n?  */
  865.         if (ch == '\n')
  866.             return;
  867.         back_ch(ch);    /* if not a line feed, then return it */
  868.         return;
  869.  
  870.     case EOF:        /* end of file -- forget it */
  871.         return;
  872.  
  873.     default:
  874.         /* scan up to three octal digits to get value */
  875.         if (isOCTAL_DIGIT(ch))
  876.         {
  877.             value = digit_value[ch];
  878.             ch = next_ch();
  879.             if (isOCTAL_DIGIT(ch))
  880.             {
  881.                 value = (value << 3) + digit_value[ch];
  882.                 ch = next_ch();
  883.                 if (isOCTAL_DIGIT(ch))
  884.                     value = (value << 3) + digit_value[ch];
  885.                 else
  886.                     back_ch(ch);
  887.             }
  888.             else
  889.                 back_ch(ch);
  890.             ch = value;
  891.         }
  892.     }
  893.  
  894.     /* Found a character to save */
  895.     save_ch(ch);
  896. }
  897.  
  898. /* Done: String */
  899. static int __stdargs  STRING(int ch)
  900. {
  901.     int nest_level = 1;
  902.  
  903.     tokenType = TOKEN_STRING;
  904.  
  905.     do
  906.     {
  907.  
  908.         ch = next_ch();
  909.         while (!isSTRING_SPECIAL(ch))
  910.         {
  911.             save_ch(ch);
  912.             ch = next_ch();
  913.         };
  914.  
  915.         switch (ch)
  916.         {
  917.  
  918.         case '(':
  919.             ++nest_level;
  920.             save_ch(ch);
  921.             break;
  922.  
  923.         case ')':
  924.             if (--nest_level > 0)
  925.                 save_ch(ch);
  926.             break;
  927.  
  928.         case '\\':
  929.             save_digraph(next_ch());
  930.             break;
  931.  
  932.         case '\r':
  933.             /* All carriage returns (\r) are turned into linefeeds (\n)*/
  934.             ch = next_ch();    /* get the next one, is it \n? */
  935.             if (ch != '\n')
  936.             {    /* if not, then put it back.   */
  937.                 back_ch(ch);
  938.             }
  939.             save_ch('\n');    /* in either case, save a linefeed */
  940.             break;
  941.  
  942.  
  943.         case EOF:
  944.             tokenType = TOKEN_INVALID;    /* Unterminated string */
  945.             nest_level = 0;
  946.             break;
  947.         }
  948.  
  949.     }
  950.     while (nest_level > 0);
  951.  
  952.     /* If there's room, add a 0-byte termination without increasing string
  953.        length.  This fixes certain dependencies on 0-terminated strings */
  954.     save_ch_no_inc(0);
  955.  
  956.     return (DONE);
  957. }
  958.  
  959.  
  960. /* -------------------------------------------------------------------
  961.  * Assemble a name; set token type and done flag.
  962.  * Put current input character back, if it is not white space.
  963.  */
  964.  
  965. /* Done: Name
  966.  *  (Safe version used to complete name tokens that
  967.  *   start out looking like something else).
  968.  */
  969.  
  970. static int __stdargs  AAH_NAME(int ch)
  971. {
  972.     do
  973.     {
  974.         save_ch(ch);
  975.         ch = next_ch();
  976.     }
  977.     while (isNAME(ch));
  978.  
  979.     back_ch_not_white(ch);
  980.     tokenType = TOKEN_NAME;
  981.     return (DONE);
  982. }
  983.  
  984. /* Done: Name */
  985. static int __stdargs  NAME(int ch)
  986. {
  987.     save_unsafe_ch(ch);
  988.     ch = next_ch();
  989.     if (isNAME(ch))
  990.     {
  991.         save_unsafe_ch(ch);
  992.         ch = next_ch();
  993.         if (isNAME(ch))
  994.         {
  995.             save_unsafe_ch(ch);
  996.             ch = next_ch();
  997.             if (isNAME(ch))
  998.             {
  999.                 save_unsafe_ch(ch);
  1000.                 ch = next_ch();
  1001.                 if (isNAME(ch))
  1002.                 {
  1003.                     save_unsafe_ch(ch);
  1004.                     ch = next_ch();
  1005.                     if (isNAME(ch))
  1006.                     {
  1007.                         save_unsafe_ch(ch);
  1008.                         ch = next_ch();
  1009.                         if (isNAME(ch))
  1010.                         {
  1011.                             save_unsafe_ch(ch);
  1012.                             ch = next_ch();
  1013.                             while (isNAME(ch))
  1014.                             {
  1015.                                 save_ch(ch);
  1016.                                 ch = next_ch();
  1017.                             }
  1018.                         }
  1019.                     }
  1020.                 }
  1021.             }
  1022.         }
  1023.     }
  1024.  
  1025.     back_ch_not_white(ch);
  1026.     tokenType = TOKEN_NAME;
  1027.     return (DONE);
  1028. }
  1029.  
  1030. /* Done: Literal Name */
  1031. static int __stdargs  LITERAL_NAME(int ch)
  1032. {
  1033.     if (isNAME(ch))
  1034.     {
  1035.         save_unsafe_ch(ch);
  1036.         ch = next_ch();
  1037.         if (isNAME(ch))
  1038.         {
  1039.             save_unsafe_ch(ch);
  1040.             ch = next_ch();
  1041.             if (isNAME(ch))
  1042.             {
  1043.                 save_unsafe_ch(ch);
  1044.                 ch = next_ch();
  1045.                 if (isNAME(ch))
  1046.                 {
  1047.                     save_unsafe_ch(ch);
  1048.                     ch = next_ch();
  1049.                     if (isNAME(ch))
  1050.                     {
  1051.                         save_unsafe_ch(ch);
  1052.                         ch = next_ch();
  1053.                         if (isNAME(ch))
  1054.                         {
  1055.                             save_unsafe_ch(ch);
  1056.                             ch = next_ch();
  1057.                             while (isNAME(ch))
  1058.                             {
  1059.                                 save_ch(ch);
  1060.                                 ch = next_ch();
  1061.                             }
  1062.                         }
  1063.                     }
  1064.                 }
  1065.             }
  1066.         }
  1067.     }
  1068.  
  1069.     back_ch_not_white(ch);
  1070.  
  1071.     tokenType = TOKEN_LITERAL_NAME;
  1072.     /* If there's room, add a 0-byte termination without increasing string
  1073.        length.  This fixes certain dependencies on 0-terminated strings */
  1074.     save_ch_no_inc(0);
  1075.  
  1076.     return (DONE);
  1077. }
  1078.  
  1079. /* Done: immediate Name */
  1080. static int __stdargs  IMMED_NAME(int ch)
  1081. {
  1082.     ch = next_ch();
  1083.     if (isNAME(ch))
  1084.     {
  1085.         save_unsafe_ch(ch);
  1086.         ch = next_ch();
  1087.         if (isNAME(ch))
  1088.         {
  1089.             save_unsafe_ch(ch);
  1090.             ch = next_ch();
  1091.             if (isNAME(ch))
  1092.             {
  1093.                 save_unsafe_ch(ch);
  1094.                 ch = next_ch();
  1095.                 if (isNAME(ch))
  1096.                 {
  1097.                     save_unsafe_ch(ch);
  1098.                     ch = next_ch();
  1099.                     if (isNAME(ch))
  1100.                     {
  1101.                         save_unsafe_ch(ch);
  1102.                         ch = next_ch();
  1103.                         if (isNAME(ch))
  1104.                         {
  1105.                             save_unsafe_ch(ch);
  1106.                             ch = next_ch();
  1107.                             while (isNAME(ch))
  1108.                             {
  1109.                                 save_ch(ch);
  1110.                                 ch = next_ch();
  1111.                             }
  1112.                         }
  1113.                     }
  1114.                 }
  1115.             }
  1116.         }
  1117.     }
  1118.  
  1119.     back_ch_not_white(ch);
  1120.     tokenType = TOKEN_IMMED_NAME;
  1121.     return (DONE);
  1122. }
  1123.  
  1124. /* Done: Name found while looking for something else */
  1125. static int __stdargs  OOPS_NAME(int ch)
  1126. {
  1127.     back_ch_not_white(ch);
  1128.     tokenType = TOKEN_NAME;
  1129.     return (DONE);
  1130. }
  1131.  
  1132.  
  1133. /* -------------------------------------------------------------------
  1134.  * Complete a miscellaneous token; set token type and done flag.
  1135.  */
  1136.  
  1137. /* Done: Unmatched Right Angle-Bracket */
  1138. static int __stdargs  RIGHT_ANGLE(int ch)
  1139. {
  1140.     tokenType = TOKEN_RIGHT_ANGLE;
  1141.     return (DONE);
  1142. }
  1143.  
  1144. /* Done: Unmatched Right Parenthesis */
  1145. static int __stdargs  RIGHT_PAREN(int ch)
  1146. {
  1147.     tokenType = TOKEN_RIGHT_PAREN;
  1148.     return (DONE);
  1149. }
  1150.  
  1151. /* Done: Left Brace */
  1152. static int __stdargs  LEFT_BRACE(int ch)
  1153. {
  1154.     tokenType = TOKEN_LEFT_BRACE;
  1155.     return (DONE);
  1156. }
  1157.  
  1158. /* Done: Right Brace */
  1159. static int __stdargs  RIGHT_BRACE(int ch)
  1160. {
  1161.     tokenType = TOKEN_RIGHT_BRACE;
  1162.     return (DONE);
  1163. }
  1164.  
  1165. /* Done: Left Bracket */
  1166. static int __stdargs  LEFT_BRACKET(int ch)
  1167. {
  1168.     save_unsafe_ch(ch);
  1169.     tokenType = TOKEN_LEFT_BRACKET;
  1170.     return (DONE);
  1171. }
  1172.  
  1173. /* Done: Right Bracket */
  1174. static int __stdargs  RIGHT_BRACKET(int ch)
  1175. {
  1176.     save_unsafe_ch(ch);
  1177.     tokenType = TOKEN_RIGHT_BRACKET;
  1178.     return (DONE);
  1179. }
  1180.  
  1181. /* Done: Break */
  1182. static int __stdargs  BREAK_SIGNAL(int ch)
  1183. {
  1184.     tokenType = TOKEN_BREAK;
  1185.     return (DONE);
  1186. }
  1187.  
  1188. /* Done: No Token Found */
  1189. static int __stdargs  NO_TOKEN(int ch)
  1190. {
  1191.     tokenType = TOKEN_EOF;
  1192.     return (DONE);
  1193. }
  1194.  
  1195.  
  1196. /*
  1197.  * -------------------------------------------------------------------
  1198.  *  scan_token -- scan one token from the input.  It uses a simple
  1199.  *    finite state machine to recognize token classes.
  1200.  *
  1201.  *  The input is from a file.
  1202.  *
  1203.  *  On entry --
  1204.  *
  1205.  *    inputP -> input PostScript object, a file.
  1206.  *    tokenStartP -> buffer in VM for accumulating the token.
  1207.  *    tokenMaxP -> last character in the token buffer
  1208.  *
  1209.  *  On exit --
  1210.  *
  1211.  *    tokenLength = number of characters in the token
  1212.  *    tokenTooLong = TRUE if the token did not fit in the buffer
  1213.  *    tokenType = code for the type of token parsed.
  1214.  *    tokenValue = converted value of a numeric token.
  1215.  *
  1216.  *
  1217.  * -------------------------------------------------------------------
  1218.  */
  1219. void scan_token(psobj *inputP)
  1220. {
  1221.     int ch;
  1222.     const unsigned char *stateP = s0;
  1223.     unsigned char entry;
  1224.     int __stdargs (*actionP) (int);
  1225.  
  1226.     /* Define input source */
  1227.     inputFileP = inputP->data.fileP;
  1228.     if (inputFileP == NULL)
  1229.     {
  1230.         tokenType = TOKEN_EOF;
  1231.         return;
  1232.     }
  1233.  
  1234.     /* Ensure enough space for most cases
  1235.    * (so we don't have to keep checking)
  1236.    * The length needs to cover the maximum number
  1237.    * of save_unsafe_ch() calls that might be executed.
  1238.    * That number is 11 (a sign and 10 decimal digits, e.g.,
  1239.    * when scanning -2147483648), but use MAX_NAME_LEN
  1240.    * in case someone changes that without checking.
  1241.    */
  1242.     tokenStartP = vm_next_byte();
  1243.     tokenMaxP = tokenStartP + MIN(vm_free_bytes(), MAX_STRING_LEN);
  1244.  
  1245.     if ((tokenMaxP - tokenStartP) < (MAX_NAME_LEN))
  1246.     {
  1247.         tokenLength = 0;
  1248.         tokenTooLong = TRUE;
  1249.         tokenType = TOKEN_NONE;
  1250.         tokenValue.integer = 0;
  1251.         return;
  1252.     }
  1253.  
  1254.     /* Reset token */
  1255.     tokenCharP = tokenStartP;
  1256.     tokenTooLong = FALSE;
  1257.  
  1258.     /* Scan one token */
  1259.     ch = next_ch();
  1260.     do
  1261.     {
  1262.         entry = stateP[ch];
  1263.         stateP = classActionTable[entry].nextStateP;
  1264.         actionP = classActionTable[entry].actionRoutineP;
  1265.         ch = (*actionP) (ch);
  1266.     }
  1267.     while (ch != DONE);
  1268.  
  1269.  
  1270.     /* Return results */
  1271.     tokenLength = tokenCharP - tokenStartP;
  1272. }
  1273.